// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-12-11

package filter

import (
	"context"
	"fmt"
	"gitee.com/go-libs/log"
	"strings"
)

// This component used to match equal or not equal operations.
type valueForEqual struct {
	Err       error
	ErrExists bool
	Field     Field

	expect, query string
}

// + Implemented

func (o *valueForEqual) GetError() error                       { return o.Err }
func (o *valueForEqual) GetField() Field                       { return o.Field }
func (o *valueForEqual) HasError() bool                        { return o.ErrExists }
func (o *valueForEqual) Match(ctx context.Context, v any) bool { return o.match(ctx, v) }
func (o *valueForEqual) Query() string                         { return o.query }

// + Match

func (o *valueForEqual) compare(ctx context.Context, got string) (yes bool) {
	if o.Field.GetOperator().IsEqual() {
		yes = got == o.expect
	} else {
		yes = got != o.expect
	}
	if log.Config().DebugOn() {
		log.Debugfc(ctx, `[filter][field=%s] match result: success="%v", expression="%s %s"`, o.Field.GetKey(), yes, got, o.query)
	}
	return
}

func (o *valueForEqual) match(ctx context.Context, v any) bool {
	if o.Field.GetKind().IsCount() {
		return o.matchCount(ctx, v)
	}
	return o.compare(ctx, fmt.Sprintf(`%v`, v))
}

func (o *valueForEqual) matchCount(ctx context.Context, v any) bool {
	var (
		ls []any
		ok bool
	)
	if ls, ok = v.([]any); !ok {
		if log.Config().DebugOn() {
			log.Debugfc(ctx, `[filter][field=%s] skipped: error="value not a list"`, o.Field.GetKey())
		}
		return false
	}
	return o.compare(ctx, fmt.Sprintf(`%v`, len(ls)))
}

// + Access

func (o *valueForEqual) init(str string) Value {
	o.parse(str)
	o.buildQuery()
	return o
}

func (o *valueForEqual) parse(str string) {
	if str = strings.TrimSpace(str); str != "" {
		for _, s := range []string{`'`, `"`} {
			str = strings.TrimSpace(
				strings.TrimPrefix(strings.TrimSuffix(str, s),
					s,
				),
			)
		}
		o.expect = str
	}
}

func (o *valueForEqual) buildQuery() {
	if o.expect == "" {
		o.query = fmt.Sprintf(`%s ''`, o.Field.GetOperator())
	} else {
		o.query = fmt.Sprintf(`%s %s`, o.Field.GetOperator(), o.expect)
	}
}
